﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace DeviceEntity.Tool
{
    /// <summary>
    /// Socket工具类
    /// </summary>
    public class SocketTool
    {
        /// <summary>
        /// Ping网络
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <param name="timeOut">超时时间ms</param>
        /// <returns></returns>
        static bool PingCheck(string ip, int timeOut)
        {
            try
            {
                Ping ping = new Ping();
                PingReply pr = ping.Send(ip, timeOut);
                if (pr.Status == IPStatus.Success)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="socket">Socke对象</param>
        /// <param name="ip">ip地址</param>
        /// <param name="port">端口</param>
        /// <returns></returns>
        public static bool Connect(ref Socket socket, string ip, int port)
        {
            try
            {
                if (PingCheck(ip, 3000) == false)
                {
                    return false;
                }
                if (socket == null || socket.Connected == false)
                {
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    try
                    {
                        socket.Connect(IPAddress.Parse(ip), port);
                    }
                    catch (Exception ex)
                    {
                        socket.Close();
                        socket.Dispose();
                        socket = null;
                        return false;
                    }
                }
                while (socket.Available > 0)
                {
                    byte[] read = new byte[socket.Available];
                    socket.Receive(read);
                }
                return socket.Connected;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="socket">Socket对象</param>
        /// <param name="data">发送数据</param>
        /// <param name="sendWait">发送等待ms</param>
        /// <returns></returns>
        public static async Task<bool> SendByte(Socket socket, byte[] data,int sendWait = 0)
        {
            try
            {
                if (socket.Connected == false)
                {
                    return false;
                }
                await Task.Delay(sendWait);
                return socket.Send(data) == data.Length;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="socket">Socke对象</param>
        /// <param name="data">发送数据</param>
        /// <param name="sendWait">发送等待</param>
        /// <returns></returns>
        public static async Task<bool>SendStr(Socket socket, string data, int sendWait = 0)
        {
            try
            {
                if (socket.Connected == false)
                {
                    return false;
                }
                await Task.Delay(sendWait);
                byte[] datas = Encoding.Default.GetBytes(data);
                return socket.Send(datas) == datas.Length;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="socket">Socket对象</param>
        /// <param name="timeOut">读取超时ms</param>
        /// <param name="timeWait">读取等待ms</param>
        /// <returns></returns>
        public static async Task< byte[] > ReciveByte(Socket socket, int timeOut, int timeWait)
        {
            try
            {
                //返回值buffer
                byte[] buffer = new byte[] { };
                //返回等待
                if (timeWait != 0)
                {
                    await Task.Delay(timeWait);
                }
                //循环读取
                while (true)
                {
                    //缓存区字节>0 或 超时
                    if (socket.Available > 0 || timeOut <= 0)
                    {
                        byte[] recData = new byte[socket.Available];
                        if (socket.Available > 0)
                        {
                            socket.Receive(recData);
                            //存入返回值
                            buffer = buffer.Concat(recData).ToArray();
                        }
                        await Task.Delay(50);
                        timeOut -= 50;
                        //缓存区为空或者超时1S
                        if (socket.Available == 0 || timeOut <= 0)
                            break;
                    }
                    await Task.Delay(50);
                    timeOut -= 50;
                }
                //未读取到数据
                if (buffer.Length == 0 && timeOut <= 0)
                {
                    buffer = null;
                }
                return buffer;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="socket">Socket对象</param>
        /// <param name="timeOut">读取超时ms</param>
        /// <param name="timeWait">读取等待ms</param>
        /// <returns></returns>
        public static async Task<string> ReciveStr(Socket socket, int timeOut, int timeWait)
        {
            try
            {
                //返回值buffer
                byte[] buffer = new byte[] { };
                //返回等待
                if (timeWait != 0)
                {
                    await Task.Delay(timeWait);
                }
                //循环读取
                while (true)
                {
                    //缓存区字节>0 或 超时
                    if (socket.Available > 0 || timeOut <= 0)
                    {
                        byte[] recData = new byte[socket.Available];
                        if (socket.Available > 0)
                        {
                            socket.Receive(recData);
                            //存入返回值
                            buffer = buffer.Concat(recData).ToArray();
                        }
                        await Task.Delay(50);
                        timeOut -= 50;
                        //缓存区为空或者超时1S
                        if (socket.Available == 0 || timeOut <= 0)
                            break;
                    }
                    await Task.Delay(50);
                    timeOut -= 50;
                }
                //未读取到数据
                if (buffer.Length == 0 && timeOut <= 0)
                {
                    buffer = null;
                    return "";
                }
                return Encoding.Default.GetString(buffer);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
